package deepbrain.simnetwork.network;

import java.text.DecimalFormat;

import deepbrain.simnetwork.util.SimNetUtils;

/**
 * NodeState class represents probability of a node is firing.
 * 
 * @author Li Yang
 * @create 2009-2-22
 */
public class NodeState {

	public final static NodeState CERTAIN_FIRING = new NodeState(1.0);
	public final static NodeState CERTAIN_SILENT = new NodeState(0.0);
	public final static NodeState MAXIMUM_ENTROPY = new NodeState(0.5);

	public final static NodeState getCertainState(double fireProb) {
		if (SimNetUtils.random() < fireProb)
			return CERTAIN_FIRING;
		else
			return CERTAIN_SILENT;
	}

	public final static NodeState getCertainState(boolean firing) {
		if (firing)
			return CERTAIN_FIRING;
		else
			return CERTAIN_SILENT;
	}

	protected double firingProb = 0.0;
	protected DecimalFormat format = new DecimalFormat("#0.000");

	public NodeState() {
	}

	public NodeState(double firingProb) {
		this.firingProb = firingProb;
	}

	public NodeState(NodeState nodeState) {
		this(nodeState.firingProb);
	}

	// public void setFiringProbability(double firingProb) {
	// if (firingProb > 1.0)
	// firingProb = 1.0;
	// if (firingProb < 0.0)
	// firingProb = 0.0;
	// this.firingProb = firingProb;
	// }
	//
	// public void setSilentProbability(double silentProb) {
	// if (silentProb > 1.0)
	// silentProb = 1.0;
	// if (silentProb < 0.0)
	// silentProb = 0.0;
	// this.firingProb = 1 - silentProb;
	// }

	public double getFiringProbability() {
		return firingProb;
	}

	public double getSilentProbability() {
		return 1 - firingProb;
	}

	public double getProbability(boolean firing) {
		if (firing)
			return getFiringProbability();
		else
			return getSilentProbability();
	}

	public static NodeState newNodeState(double firingProb) {
		return new NodeState(firingProb);
	}

	public static NodeState getStateFromString(String string) {
		if (string == null)
			return CERTAIN_SILENT;
		String trim = string.trim();
		return newNodeState(Double.parseDouble(trim));
	}

	@Override
	public int hashCode() {
		return (int) (firingProb * 1073741824);
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof NodeState))
			return false;
		NodeState nodeState2 = (NodeState) obj;
		if (firingProb == nodeState2.firingProb)
			return true;
		return false;
	}

	public boolean isCertainFiring() {
		return (firingProb == 1.0);
	}

	public boolean isCertainSilent() {
		return (firingProb == 0.0);
	}

	@Override
	public String toString() {
		if (isCertainFiring()) {
			return "FIRING";
		}
		if (isCertainSilent()) {
			return "SILENT";
		}
		return "Prob{FIRING:[" + format.format(firingProb) + "]}";
	}

	public String toStringBrief() {
		if (isCertainFiring())
			return "1";
		if (isCertainSilent())
			return "0";
		return format.format(firingProb);
	}

}
